/**
 * $Revision: 1.3 $
 * $Date: 2010/07/14 14:23:32 $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.spark.ui;

import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.spark.PresenceManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.CheckNode;
import org.jivesoftware.spark.component.CheckTree;
import org.jivesoftware.spark.component.TitlePanel;
import org.jivesoftware.spark.component.renderer.JPanelRenderer;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.spark.util.log.Log;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;



/**
 * The <code>RosterPickList</code> is used as a pick list of users within ones Roster.
 */
public class RosterPickList extends JPanel {
    private DefaultListModel model = new DefaultListModel();
    private JList rosterList = new JList(model);
    private JCheckBox OfflineUsers = new JCheckBox(Res.getString("checkbox.broadcast.hide.offline.user"));
    private ArrayList<ArrayList<Object>> NodesGroups = new ArrayList<ArrayList<Object>>();
    private List<CheckNode> nodes = new ArrayList<CheckNode>();
    private List<CheckNode> nodes2 = new ArrayList<CheckNode>();
    private List<CheckNode> groupNodes = new ArrayList<CheckNode>();
    private CheckNode rosterNode; 
    private CheckTree checkTree; 
    private Integer OfflineGroup;
    private final ContactList contactList;
    private boolean isAddSelectedContacts = true;
    
    /**
     * Creates a new instance of the RosterBrowser.
     */
    public RosterPickList() {
        setLayout(new GridBagLayout());
        
        rosterNode = new CheckNode(Res.getString("title.roster"));
        checkTree = new CheckTree(rosterNode);
        contactList = SparkManager.getWorkspace().getContactList();
        
        // modify by sidneyren to be a selected tree
        // creates the List for the Online Users
        String groupName = "Online";
        CheckNode groupNode = new CheckNode(groupName);
        groupNodes.add(groupNode);
        rosterNode.add(groupNode);
        //ContactGroup group includes online contact;
        for(ContactGroup group : contactList.getContactGroups())
	        for (ContactItem item : group.getContactItems()) 
	        {
	      	  if(item.isAvailable())
	      	  {
	           CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon());
	           itemNode.setAssociatedObject(item.getJID());
	           groupNode.add(itemNode);
	           nodes.add(itemNode);
	      	  }
	        }

        // Build out from Roster
       
        for (ContactGroup group : contactList.getContactGroups()) {
            groupName = group.getGroupName();
            //判断重复的组名并不把它加入到树中
            int j = 0;
            for(CheckNode cn :groupNodes){
	            if(groupName.equals(cn.getUserObject().toString())){
	            	j=1;
	            }
            }
            if(j==1)continue;
            
//            if (!group.hasAvailableContacts()) {
//                continue;
//            }
            
            //不显示联系联系人组
//            if(group.getGroupName().equals(Res.getString("group.offline"))){
//            	continue;
//            }
            groupNode = new CheckNode(groupName);
            groupNodes.add(groupNode);
            rosterNode.add(groupNode);
            
            // Now add contact items from contact group.
            for (ContactItem item : group.getContactItems()) {
                CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon());
                itemNode.setAssociatedObject(item.getJID());
                groupNode.add(itemNode);
                nodes.add(itemNode);
            }

            //add offline items to group
            
            final List<ContactItem> offlineContacts = new ArrayList<ContactItem>(group.getOfflineContacts());
            Collections.sort(offlineContacts, ContactList.ContactItemComparator);

            for (ContactItem item : offlineContacts) {
                CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon());
                itemNode.setAssociatedObject(item.getJID());
                groupNode.add(itemNode);
                nodes.add(itemNode);
            }

        }

        final JScrollPane treePane = new JScrollPane(checkTree);
        treePane.setBorder(BorderFactory.createTitledBorder(Res.getString("message.send.to.these.people")));

        // Add to UI
        add(treePane, new GridBagConstraints(1, 0, 1, 3, 0.5, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0));
        add(OfflineUsers, new GridBagConstraints(1, 3, 1, 0, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0));
        
        OfflineUsers.addActionListener(new ActionListener()
 	     {
      	  public void actionPerformed(ActionEvent e)
      	  {
      		  hideOfflineUsers();
           }
 	     });
        

//        checkTree.expandTree();
        checkTree.expandRootNode();

        

//        rosterList.setCellRenderer(new JPanelRenderer());
//
//        JLabel rosterLabel = new JLabel();
//        this.add(rosterLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
//        this.add(new JScrollPane(rosterList), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));

//        ResourceUtils.resLabel(rosterLabel, rosterList, Res.getString("label.available.users.in.roster"));
        
    }
    
    /**
     * 添加选中的contacts到树中
     */
    public void addSelectedContacts(){
    	 // Iterate through selected users.
        for (ContactItem item : contactList.getSelectedUsers()) {
            for (CheckNode node : nodes) {
                if (node.getAssociatedObject().toString().equals(item.getJID())) {
                    node.setSelected(true);
                }
            }
        }
    }
    
    public Collection showRoster(JDialog parent,boolean isAddSelectedContacts){
    	this.isAddSelectedContacts= isAddSelectedContacts;
    	return showRoster(parent);
    }
    
    /**
     * Displays a pick list of available users within their roster.
     * add selected tree through add construct of RosterPickList into pane 
     * @param parent the parent container.
     * @return all items choosen in the pick list.
     */
    public Collection showRoster(JDialog parent) {
    	
    	if(isAddSelectedContacts){
    		addSelectedContacts();
    	}
        final List<ContactItem> userList = new ArrayList<ContactItem>();

        // Populate Invite Panel with Available users.
        final Roster roster = SparkManager.getConnection().getRoster();
        for (RosterEntry entry : roster.getEntries()) {
            Presence presence = PresenceManager.getPresence(entry.getUser());
            if (presence.isAvailable()) {
                ContactItem item = new ContactItem(entry.getName(), null, entry.getUser());
                item.setPresence(presence);
                userList.add(item);
            }
        }

        // Sort Users
        Collections.sort(userList, itemComparator);

        for (ContactItem item : userList) {
            model.addElement(item);
        }

        final JOptionPane pane;


        TitlePanel titlePanel;

        // Create the title panel for this dialog
        titlePanel = new TitlePanel(Res.getString("title.roster"), Res.getString("message.select.one.or.more"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true);

        // Construct main panel w/ layout.
        final JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(titlePanel, BorderLayout.NORTH);

        // The user should only be able to close this dialog.
        Object[] options = {Res.getString("ok"), Res.getString("cancel")};
        pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]);

        mainPanel.add(pane, BorderLayout.CENTER);

        final JOptionPane p = new JOptionPane();

        final JDialog dlg = p.createDialog(parent, Res.getString("title.roster"));
        dlg.setModal(true);
        dlg.pack();
        dlg.setSize(350, 450);
        dlg.setResizable(true);
        dlg.setContentPane(mainPanel);
        dlg.setLocationRelativeTo(parent);

        PropertyChangeListener changeListener = new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String value = (String)pane.getValue();
                if (Res.getString("cancel").equals(value)) {
                	nodes.clear();
//                	rosterList.clearSelection();
                    pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
                    dlg.dispose();
                }
                else if (Res.getString("ok").equals(value)) {
                    pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
                    dlg.dispose();
                }
            }
        };

        pane.addPropertyChangeListener(changeListener);

        dlg.setVisible(true);
        dlg.toFront();
        dlg.requestFocus();

        List<String> selectedContacts = new ArrayList<String>();

//        Object[] values = rosterList.getSelectedValues();
//        final int no = values != null ? values.length : 0;
//        for (int i = 0; i < no; i++) {
//            try {
//                ContactItem item = (ContactItem)values[i];
//                selectedContacts.add(item.getJID());
//            }
//            catch (NullPointerException e) {
//                Log.error(e);
//            }
//        }
        
        for (CheckNode node : nodes) {
        	if(node.isSelected())
			selectedContacts.add(node.getAssociatedObject().toString());
		}

        return selectedContacts;
    }


    /**
     * Sorts ContactItems.
     */
    final Comparator<ContactItem> itemComparator = new Comparator<ContactItem>() {
        public int compare(ContactItem item1, ContactItem item2) {
            String nickname1 = item1.getDisplayName();
            String nickname2 = item2.getDisplayName();
            if (nickname1 == null || nickname2 == null) {
                return 0;
            }

            return nickname1.toLowerCase().compareTo(nickname2.toLowerCase());

        }
    };
    
    /**
     * hide offline Users 
     */
    private void hideOfflineUsers()
    {
   	 
   	  int i = 0;
		  if(OfflineUsers.isSelected())
		  {
			  final ContactList contactList = SparkManager.getWorkspace().getContactList();
			  i = 0;
			  for(CheckNode node : nodes)
			  {
				  if(contactList.getContactItemByDisplayName(node.toString()).getPresence().getType() == Presence.Type.unavailable)
				  {
					  if(node.getParent() != null)
					  {
					  TreeNode parent = node.getParent();
					  TreeNode[] path = ((DefaultTreeModel)checkTree.getTree().getModel()).getPathToRoot(parent);
					  ((DefaultTreeModel)checkTree.getTree().getModel()).removeNodeFromParent(node);
					  checkTree.getTree().setSelectionPath(new TreePath(path));
					  NodesGroups.add(new ArrayList<Object>());
					  NodesGroups.get(i).add(parent);
					  NodesGroups.get(i).add(node);
					  i++;
					  }
				  }
			  }
			  for(int x = 0; x < groupNodes.size(); x++)
			  {
				  if(groupNodes.get(x).toString().equals(Res.getString("group.offline")))
				  {
					  OfflineGroup = x;
					  TreeNode parent = groupNodes.get(x).getParent();
					  TreeNode[] path = ((DefaultTreeModel)checkTree.getTree().getModel()).getPathToRoot(parent);
					  ((DefaultTreeModel)checkTree.getTree().getModel()).removeNodeFromParent(groupNodes.get(x));
					  checkTree.getTree().setSelectionPath(new TreePath(path));
				  }
			  }
		  }
		  else
		  {
			  i = 0;
			  DefaultMutableTreeNode child = groupNodes.get(OfflineGroup);
			  ((DefaultTreeModel)checkTree.getTree().getModel()).insertNodeInto(child, rosterNode, rosterNode.getChildCount()); 
			  TreeNode[] path = ((DefaultTreeModel)checkTree.getTree().getModel()).getPathToRoot(rosterNode);
			  checkTree.getTree().expandPath(new TreePath(path));
			  checkTree.expandRootNode();
			  for(CheckNode node : nodes)
			  {
				  if(node.getParent() == null)
				  {
					  child = (CheckNode)NodesGroups.get(i).get(1);
					  ((DefaultTreeModel)checkTree.getTree().getModel()).insertNodeInto(child, ((CheckNode) NodesGroups.get(i).get(0)), ((CheckNode) NodesGroups.get(i).get(0)).getChildCount()); 
//					  path = ((DefaultTreeModel)checkTree.getTree().getModel()).getPathToRoot(node);
//					  checkTree.getTree().expandPath(new TreePath(path));
					  checkTree.expandRootNode();
					  i++;
				  }
			  }
		  }
    }
}
